abc languageのBNFとvscode syntax
code:正解はこれ.json
{
"scopeName": "source.abc",
"patterns": "include": "#expression" },
"repository": {
"expression": {
"patterns": "include": "#letter" }, { "include": "#paren-expression" }
},
"letter": {
"match": "a|b|c",
"name": "keyword.letter"
},
"paren-expression": {
"begin": "\\(",
"end": "\\)",
"beginCaptures": {
"0": { "name": "punctuation.paren.open" }
},
"endCaptures": {
"0": { "name": "punctuation.paren.close" }
},
"name": "expression.group",
"patterns": "include": "#expression" }
}
}
}
BNF
code:abc_languageの場合どうなるか.bnf
<expression> ::= <letter> | <paren-expression>
<paren-expression> ::= "(" <expression> ")"
これじゃねえよなぁ
a(b(c))とかできないし
code:abc_languageの場合どうなるか.bnf
<expression> ::= <letter><expression> | <paren-expression><expression> | ""
<paren-expression> ::= "(" <expression> ")"
こうだよね
で、BNFから一体何をどうしたら上記の正解になるのか
<expression> ::= <letter><expression> | <paren-expression><expression> | ""
code:json
"expression": {
"patterns": "include": "#letter" }, { "include": "#paren-expression" }
},
一般化すると
A := aA | bA | cA ... | ""
code:json
"A" : {
"patterns" : [
{"include" : "a"},
{"include" : "b"},
{"include" : "c"},
]
}
なんか因数分解みたいですねwsta.icon
letter
一般化すると
リーフトークンは普通に正規表現で記せばよい
<paren-expression> ::= "(" <expression> ")"
code:json
"paren-expression": {
"begin": "\\(",
"end": "\\)",
"beginCaptures": {
"0": { "name": "punctuation.paren.open" }
},
"endCaptures": {
"0": { "name": "punctuation.paren.close" }
},
"name": "expression.group",
"patterns": "include": "#expression" }
}
一般化すると
beginとendは正規表現で記せばよい
beginとend、それぞれに名前を与えること
中身は patterns で列挙すればよい